package com.dongbao.utils;

import com.dongbao.module.CallMethod;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.PsiCommentImpl;
import com.intellij.psi.impl.source.tree.java.*;
import com.intellij.util.Processor;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

public class IDEAUtil {

    /**
     * 获取一段代码在class中所在的行与列
     * */
    public static int getLineAndColumn(PsiClass psiClass, PsiElement element){
        Document document = PsiDocumentManager.getInstance(psiClass.getProject()).getDocument(psiClass.getContainingFile());
        int lineNumber = document.getLineNumber(element.getTextOffset());
        return lineNumber;
    }

    /**
     * 获取一段代码在class中所在的行与列
     * */
    public static int getLineAndColumn(PsiFile psiFile, PsiElement element){
        Document document = PsiDocumentManager.getInstance(psiFile.getProject()).getDocument(psiFile);
        int lineNumber = document.getLineNumber(element.getTextOffset());
        return lineNumber;
    }

    /**
     * 子节点代码行解析
     * */
    public static void chindPsiRow(PsiMethod method, PsiElement element, Consumer<PsiElement> action){
        if(element instanceof PsiCommentImpl){
            /* 注释信息 */
        }else if(element instanceof PsiReturnStatementImpl){
            /* return 返回 */
            PsiReturnStatementImpl returnStatement=(PsiReturnStatementImpl)element;
            /* return中存在的方法调用 */
            for(PsiElement returnElement:returnStatement.getChildren()){
                chindPsiRow(method,returnElement,action);
            }
        }else if(element instanceof PsiDeclarationStatementImpl){
            /* 表达式调用 */
            PsiDeclarationStatementImpl statement=(PsiDeclarationStatementImpl)element;
            action.accept(statement);
        }else if(element instanceof PsiTryStatementImpl){
            /* 表达式调用 */
            PsiTryStatementImpl tryStatement=(PsiTryStatementImpl)element;
            PsiElement[] children = tryStatement.getChildren();
            for(PsiElement childrenElement:children){
                chindPsiRow(method,childrenElement,action);
            }
        }else if(element instanceof PsiIfStatementImpl){
            /* 表达式调用 */
            PsiIfStatementImpl tryStatement=(PsiIfStatementImpl)element;
            PsiElement[] children = tryStatement.getChildren();
            for(PsiElement childrenElement:children){
                chindPsiRow(method,childrenElement,action);
            }
        }else if(element instanceof PsiExpressionStatementImpl){
            PsiExpressionStatementImpl expressionStatement = (PsiExpressionStatementImpl)element;
            PsiElement[] expElements = expressionStatement.getChildren();
            if(expressionStatement.getText().indexOf("log.")!=-1 || expressionStatement.getText().indexOf("LOG.")!=-1 ){
                /* 对日志记录的表达式不进行处理 */
                return;
            }
            for(PsiElement expElement:expElements){
                /* 拆分节点去解析内部是否存在方法调用的 */
                chindPsiRow(method,expElement,action);
            }
        }else if(element instanceof PsiMethodCallExpressionImpl){
            PsiMethodCallExpressionImpl methodCallExpressionImpl = (PsiMethodCallExpressionImpl)element;
            action.accept(methodCallExpressionImpl);
        }else if(element instanceof PsiBlockStatementImpl){
            PsiBlockStatementImpl boockStatem = (PsiBlockStatementImpl)element;
            for(PsiElement childrenElement:boockStatem.getChildren()){
                chindPsiRow(method,childrenElement,action);
            }
        }else if(element instanceof PsiAssignmentExpressionImpl){
            PsiAssignmentExpressionImpl assignmentExpr = (PsiAssignmentExpressionImpl)element;
            PsiElement[] children = element.getChildren();
            for(PsiElement childrenElement:children){
                chindPsiRow(method,childrenElement,action);
            }
        }else if(element instanceof PsiMethodCallExpressionImpl){
            CallMethod statementMethodCall = getStatementMethodCall(element,method);
            action.accept(element);
        }else{
            if(element.getChildren().length!=0){
                PsiElement[] children = element.getChildren();
                for(PsiElement childrenElement:children){
                    chindPsiRow(method,childrenElement,action);
                }
            }
        }
    }

    /**
     * 获取到当前的传入对象字节点的方法调用的方法
     * */
    private static CallMethod getStatementMethodCall(PsiElement element, PsiMethod method){
        CallMethod callMethod=new CallMethod();
        if(element instanceof PsiMethodCallExpressionImpl){
            PsiMethodCallExpressionImpl methodCallExpressionImpl = (PsiMethodCallExpressionImpl)element;
            callMethod.setMothodCall(methodCallExpressionImpl);
            PsiMethod psiMethod = callMethod.getMothodCall().resolveMethod();
            if(psiMethod!=null){
                callMethod.setPsiClass(psiMethod.getContainingClass());
                callMethod.setMethod(psiMethod);
            }
            /* 从方法调用的表达式中获取到对应调用的类和方法 */
//            analysisClassAndMethod(callMethod,methodCallExpressionImpl,method);
            return callMethod;
        }else if(element.getChildren().length!=0){
            for(PsiElement childElement:element.getChildren()){
                CallMethod childCallMethod = getStatementMethodCall(childElement,method);
                if(childCallMethod!=null && childCallMethod.getMethod()!=null){
                    return childCallMethod;
                }
            }
        }else {
            return null;
        }
        return null;
    }

}
